////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_SCRIPTING_TOP_LEVEL_ELEMENT_H__
#define __WN_SCRIPTING_TOP_LEVEL_ELEMENT_H__

#include "WNScripting/inc/WNParseNode.h"

#include <deque>

namespace llvm {
    class Value;
    class Function;
};

namespace WNScripting {
    class WNDataType;
    class WNTopLevelElementList;
    class WNInstructionList;
    class WNInstruction;
    class WNFunctionHeaderList;
    struct WNFunction;


    class WNTopLevelElement : public WNParseNode {
    public:
        virtual ~WNTopLevelElement();
        WNTopLevelElement(WN_SIZE_T _startLine,
                          WN_SIZE_T _endLine,
                          WN_SIZE_T _startChar,
                          WN_SIZE_T _endChar,
                          WN_BOOL   _stackRet,
                          WNDataType* _dataType,
                          WNIdentifierElement _functionName,
                          WNInstructionList* _instructionList);
        WNTopLevelElement(WN_SIZE_T _startLine,
                           WN_SIZE_T _endLine,
                           WN_SIZE_T _startChar,
                           WN_SIZE_T _endChar,
                           WN_BOOL   _stackRet,
                           WNDataType* _dataType,
                           WNIdentifierElement _functionName,
                           WNInstructionList* _instructionList,
                           WNFunctionHeaderList* _header);
        virtual llvm::Value* OptimizeAndGenerate(WNScriptingEngineData& _scriptingData, WNFunctionDecl* _functionDecl);
        llvm::Function* OptimizeAndGenerateFunction(WNScriptingEngineData& _scriptingData, WNFunction** _fileName);
        virtual WN_BOOL ReportErrors();

    private:
        WNDataType* mDataType;
        WN_BOOL  mStackRet;
        WNIdentifierElement mFunctionName;
        WNFunctionHeaderList* mFunctionHeaderList;
        WNInstructionList* mInstructionList;
        std::deque<WNInstruction*> mInstructions;
    };

    class WNTopLevelElementList : public WNParseNode {
    public:
        ~WNTopLevelElementList();
        WNTopLevelElementList(WN_SIZE_T _startLine,
                          WN_SIZE_T _endLine,
                          WN_SIZE_T _startChar,
                          WN_SIZE_T _endChar);

        WNTopLevelElementList(WN_SIZE_T _startLine,
                          WN_SIZE_T _endLine,
                          WN_SIZE_T _startChar,
                          WN_SIZE_T _endChar,
                          WNTopLevelElement* _topLevelElement,
                          WNTopLevelElementList* _topLevelElementList);
        WNTopLevelElement* AppropriateElement(){ WNTopLevelElement * elem = mTopLevelElement; mTopLevelElement = WN_NULL; return elem; }
        WNTopLevelElementList* AppropriateElementList() { WNTopLevelElementList * elem = mTopLevelElementList; mTopLevelElementList = WN_NULL; return elem; }
        virtual llvm::Value* OptimizeAndGenerate(WNScriptingEngineData& scriptingData, WNFunctionDecl* functionDecl);

    private:
        WNTopLevelElement* mTopLevelElement;
        WNTopLevelElementList* mTopLevelElementList;
    };
}
#endif // __WN_SCRIPTING_TOP_LEVEL_ELEMENT_H__